#pragma once
#include <iostream>
#include <functional>

class Connection;
class Reactor;

using io_handler_t = std::function<void(Connection *)>;

class Connection
{
public:
    Connection() {}
    Connection(int fd, uint32_t event, io_handler_t reader, io_handler_t writer, io_handler_t exceptor, Reactor *R)
        : _fd(fd), _event(event), _reader(reader), _writer(writer), _exceptor(exceptor), _R(R)
    {
    }

    bool OutEmpty()
    {
        return _outbuffer.empty();
    }

    int GetFd()
    {
        return _fd;
    }

    uint32_t GetEvent()
    {
        return _event;
    }

    void SetEvent(uint32_t event)
    {
        _event = event;
    }

    std::string &GetInbuffer()
    {
        return _inbuffer;
    }

    std::string &GetOutbuffer()
    {
        return _outbuffer;
    }

    std::string &GetExcebuffer()
    {
        return _excebuffer;
    }

    Reactor *GetReactor()
    {
        return _R;
    }

    io_handler_t GetWriter()
    {
        return _writer;
    }

    io_handler_t GetReader()
    {
        return _reader;
    }
    io_handler_t GetExceptor()
    {
        return _exceptor;
    }

    ~Connection() {}

private:
    int _fd = -1;
    uint32_t _event = -1;
public:
    std::string _inbuffer;
    std::string _outbuffer;
    std::string _excebuffer;

    io_handler_t _reader = nullptr;
    io_handler_t _writer = nullptr;
    io_handler_t _exceptor = nullptr;

    Reactor *_R;
};

class Factory
{
public:
    static Connection *BuildListenConn(int fd, uint32_t event, io_handler_t reader, Reactor *R)
    {
        return new Connection(fd, event, reader, nullptr, nullptr, R);
    }

    static Connection *BuildNormalConn(int fd, uint32_t event,
                                       io_handler_t reader, io_handler_t writer, io_handler_t exceptor, Reactor *R)
    {
        return new Connection(fd, event, reader, writer, exceptor, R);
    }
};